#include "../../../shared/infra/etcd.hpp"
#include "../../../shared/infra/channel.hpp"
#include "../main.pb.h"
#include <brpc/channel.h>
#include <chrono>
#include <gflags/gflags.h>
#include <memory>
#include <string>
#include <thread>

DEFINE_bool(run_mode, false, "程序的运行模式, false-调试 true-发布");
DEFINE_string(log_file, "", "发布模式下，指定日志输出文件");
DEFINE_int32(log_level, 0, "发布模式下，指定日志输出等级");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(call_service, "/service/echo", "当前实例名称");

int main(int argc, char* argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    shared::init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    // 1.构造rpc服务管理对象
    shared::infra::RpcServiceManagerPtr serviceManager = std::make_shared<shared::infra::RpcServiceManager>();
    serviceManager->declared(FLAGS_call_service);   
    auto putCb = std::bind(
        &shared::infra::RpcServiceManager::onServiceOnline, serviceManager.get(), 
        std::placeholders::_1, std::placeholders::_2
    );
    auto delCb = std::bind(
        &shared::infra::RpcServiceManager::onServiceOffline, serviceManager.get(), 
        std::placeholders::_1, std::placeholders::_2
    );

    // 2.构造服务发现对象
    shared::infra::DiscoveryPtr client = std::make_shared<shared::infra::Discovery>(
        FLAGS_etcd_host, FLAGS_base_service, putCb, delCb
    );

    while (1) 
    {
        // 1.获取该服务的rpc信道对象
        shared::infra::RpcServiceChannel::ChannelPtr channel = serviceManager->choose(FLAGS_call_service);
        if(!channel) {
            this_thread::sleep_for(std::chrono::seconds(1));
            continue;
        }

        // 2.构造EchoService_Stub对象，用于rpc调用
        example::EchoService_Stub stub(channel.get());
        example::EchoRequest req;
        req.set_message("this is a brpc test-demo");
        brpc::Controller* controller = new brpc::Controller();
        example::EchoResponse* resp = new example::EchoResponse();
        
        // 2-1  nullptr 同步调用
        // 异步调用示例: 
        //    google::protobuf::Closure* done = google::protobuf::NewCallback(&HandleResponse);
        //    stub.Echo(controller, &req, resp, done);
        stub.Echo(controller, &req, resp, nullptr);  
        if (controller->Failed() == true) {
            std::cout << "rpc调用失败: " << controller->ErrorText() << std::endl;
            delete controller;
            delete resp;
            std::this_thread::sleep_for(std::chrono::seconds(1));
            continue;
        }
        std::cout << "收到响应: " << resp->message() << "\n";
        delete controller;
        delete resp;
        this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}